package pipeline

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// FileCheckpointManager 基于文件的检查点管理器
type FileCheckpointManager struct {
	checkpointDir string
}

// NewCheckpointManager 创建检查点管理器
func NewCheckpointManager(checkpointDir string) CheckpointManager {
	return &FileCheckpointManager{
		checkpointDir: checkpointDir,
	}
}

// SaveCheckpoint 保存检查点
func (cm *FileCheckpointManager) SaveCheckpoint(task *PipelineTask) error {
	// 确保检查点目录存在
	if err := os.MkdirAll(cm.checkpointDir, 0755); err != nil {
		return fmt.Errorf("failed to create checkpoint directory: %w", err)
	}

	// 创建检查点数据
	checkpoint := &TaskCheckpoint{
		TaskID:    task.ID,
		FilePath:  task.FilePath,
		FileName:  task.FileName,
		Config:    task.Config,
		Progress:  task.GetProgress(),
		CreatedAt: task.CreatedAt,
		UpdatedAt: task.UpdatedAt,
		SavedAt:   task.UpdatedAt,
	}

	// 序列化为JSON
	data, err := json.MarshalIndent(checkpoint, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to marshal checkpoint: %w", err)
	}

	// 写入文件
	checkpointFile := filepath.Join(cm.checkpointDir, fmt.Sprintf("%s.json", task.ID))
	if err := ioutil.WriteFile(checkpointFile, data, 0644); err != nil {
		return fmt.Errorf("failed to write checkpoint file: %w", err)
	}

	return nil
}

// LoadCheckpoint 加载检查点
func (cm *FileCheckpointManager) LoadCheckpoint(taskID string) (*PipelineTask, error) {
	checkpointFile := filepath.Join(cm.checkpointDir, fmt.Sprintf("%s.json", taskID))

	// 检查文件是否存在
	if _, err := os.Stat(checkpointFile); os.IsNotExist(err) {
		return nil, fmt.Errorf("checkpoint not found for task: %s", taskID)
	}

	// 读取文件
	data, err := ioutil.ReadFile(checkpointFile)
	if err != nil {
		return nil, fmt.Errorf("failed to read checkpoint file: %w", err)
	}

	// 反序列化
	var checkpoint TaskCheckpoint
	if err := json.Unmarshal(data, &checkpoint); err != nil {
		return nil, fmt.Errorf("failed to unmarshal checkpoint: %w", err)
	}

	// 重建任务
	task := &PipelineTask{
		ID:        checkpoint.TaskID,
		FilePath:  checkpoint.FilePath,
		FileName:  checkpoint.FileName,
		Config:    checkpoint.Config,
		Progress:  checkpoint.Progress,
		CreatedAt: checkpoint.CreatedAt,
		UpdatedAt: checkpoint.UpdatedAt,
	}

	return task, nil
}

// DeleteCheckpoint 删除检查点
func (cm *FileCheckpointManager) DeleteCheckpoint(taskID string) error {
	checkpointFile := filepath.Join(cm.checkpointDir, fmt.Sprintf("%s.json", taskID))

	if err := os.Remove(checkpointFile); err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("failed to delete checkpoint file: %w", err)
	}

	return nil
}

// ListCheckpoints 列出所有检查点
func (cm *FileCheckpointManager) ListCheckpoints() ([]string, error) {
	// 检查目录是否存在
	if _, err := os.Stat(cm.checkpointDir); os.IsNotExist(err) {
		return []string{}, nil
	}

	// 读取目录
	files, err := ioutil.ReadDir(cm.checkpointDir)
	if err != nil {
		return nil, fmt.Errorf("failed to read checkpoint directory: %w", err)
	}

	var taskIDs []string
	for _, file := range files {
		if !file.IsDir() && strings.HasSuffix(file.Name(), ".json") {
			taskID := strings.TrimSuffix(file.Name(), ".json")
			taskIDs = append(taskIDs, taskID)
		}
	}

	return taskIDs, nil
}

// TaskCheckpoint 任务检查点数据结构
type TaskCheckpoint struct {
	TaskID    string        `json:"task_id"`
	FilePath  string        `json:"file_path"`
	FileName  string        `json:"file_name"`
	Config    *TaskConfig   `json:"config"`
	Progress  *TaskProgress `json:"progress"`
	CreatedAt time.Time     `json:"created_at"`
	UpdatedAt time.Time     `json:"updated_at"`
	SavedAt   time.Time     `json:"saved_at"`
}

// RecoveryManager 恢复管理器
type RecoveryManager struct {
	checkpointManager CheckpointManager
	pipeline          *PipelineManager
}

// NewRecoveryManager 创建恢复管理器
func NewRecoveryManager(checkpointManager CheckpointManager, pipeline *PipelineManager) *RecoveryManager {
	return &RecoveryManager{
		checkpointManager: checkpointManager,
		pipeline:          pipeline,
	}
}

// RecoverTasks 恢复任务
func (rm *RecoveryManager) RecoverTasks() error {
	// 获取所有检查点
	taskIDs, err := rm.checkpointManager.ListCheckpoints()
	if err != nil {
		return fmt.Errorf("failed to list checkpoints: %w", err)
	}

	var recoveredCount int
	var errors []string

	for _, taskID := range taskIDs {
		// 加载检查点
		task, err := rm.checkpointManager.LoadCheckpoint(taskID)
		if err != nil {
			errors = append(errors, fmt.Sprintf("failed to load checkpoint %s: %v", taskID, err))
			continue
		}

		// 检查任务状态
		if task.Progress.Status == StatusProcessing {
			// 重新提交任务
			_, err := rm.pipeline.SubmitTask(task.FilePath, task.Config)
			if err != nil {
				errors = append(errors, fmt.Sprintf("failed to resubmit task %s: %v", taskID, err))
				continue
			}

			recoveredCount++
		}

		// 删除旧检查点
		rm.checkpointManager.DeleteCheckpoint(taskID)
	}

	if len(errors) > 0 {
		return fmt.Errorf("recovered %d tasks with errors: %v", recoveredCount, errors)
	}

	return nil
}
